//////////////////////////////////////////////////////////////////////////
#pragma once
//////////////////////////////////////////////////////////////////////////
#include <cassert>
//////////////////////////////////////////////////////////////////////////
template<class RETURN>
class Functor
{
public:
	virtual ~Functor(){};
	virtual RETURN operator()() = 0;
};
//////////////////////////////////////////////////////////////////////////
template<class RETURN, class ARG>
class FunctorArg
{
public:
	virtual ~FunctorArg(){};
	virtual RETURN operator()(ARG) = 0;
};
//////////////////////////////////////////////////////////////////////////
template<class RETURN, class CLASS>
class FunctorImpl: public Functor<RETURN>
{
public:
	FunctorImpl(CLASS* obj, RETURN (CLASS::*method)())
	: m_obj(obj)
	, m_method(method)
	{

	}

	RETURN operator()()
	{
		assert(m_obj && m_method);
		return (m_obj->*m_method)();	
	}

private:
	CLASS* m_obj;
	RETURN (CLASS::*m_method)();
};
//////////////////////////////////////////////////////////////////////////
template<class RETURN, class CLASS, class ARG>
class FunctorArgImpl: public FunctorArg<RETURN, ARG>
{
public:
	FunctorArgImpl(CLASS* obj, RETURN (CLASS::*method)(ARG))
		: m_obj(obj)
		, m_method(method)
	{

	}

	RETURN operator()(ARG arg)
	{
		assert(m_obj && m_method);
		return (m_obj->*m_method)(arg);
	}

private:
	CLASS* m_obj;
	RETURN (CLASS::*m_method)(ARG);
};
//////////////////////////////////////////////////////////////////////////
template<class RETURN, class CLASS>
Functor<RETURN>* createFunctor(CLASS* obj, RETURN (CLASS::*method)())
{
	return new FunctorImpl<RETURN, CLASS>(obj, method);
}
//////////////////////////////////////////////////////////////////////////
template<class RETURN, class CLASS, class ARG>
FunctorArg<RETURN, ARG>* createFunctorArg(CLASS* obj, RETURN (CLASS::*method)(ARG))
{
	return new FunctorArgImpl<RETURN, CLASS, ARG>(obj, method);
}